//
//  CertTLV.m
//  TestProject
//
//  Created by 武侠 on 2022/2/17.
//  Copyright © 2022 zhulong. All rights reserved.
//

#import "CertTLV.h"

@implementation CertTLV

// 计算
+ (NSString *)value: (char *)data begin: (int)begin {
    int type = data[begin];
    CertItemLength *length = [[CertItemLength alloc] initWithData:data index:begin+1];
    switch ((uint8_t)type) {
        case 0x01:          // Bool
            return [self boolFromValue:data begin:begin length:length];
        case 0x02:          // Int 类型
            return [self intFromValue:data begin:begin length:length];
        case 0x03:          // Bit String 比特串
        case 0x04:          // Octet String 字节码串
            return [self octetStringFromValue:data begin:begin length:length];
        case 0x05:          // NULL
            break;
        case 0x06:          // 对象标识符 OID
            return [self oidFromValue:data begin:begin length:length];
        case 0x0c:          // UTF8 String 类型
            return [self utf8StringFromValue:data begin:begin length:length];
        case 0x1e:          // BMP String (Unicode)
            return [self unicodeStringFromValue:data begin:begin length:length];
        case 0x17:          // UTime 类型
            return [self utimeStringFromValue:data begin:begin length:length];
        case 0x13:          // ASCII 字符串
        case 0x14:          // T61 String
        case 0x16:          // IA5 String类型
        case 0x82:          //
        case 0x86:          // 特殊IA5String类型
            return [self uasciiStringFromValue:data begin:begin length:length];
        case 0x30:          // 数组
        case 0x31:          // Set
        {// 31 14 80 12 34 31 31 33 32 33 31 39 39 31 30 31 30 33 33 38 33 58
            NSMutableString *str = [NSMutableString string];
            int i = begin + 1 + length.lenLen;
            while (i < begin + 1 + length.len + length.lenLen) {
                type = data[i];
                CertItemLength *slength = [[CertItemLength alloc] initWithData:data index:i+1];
                NSString *sa = [self value:data begin:i];
                if (sa.length > 0) {
                    if ((uint8_t)type == 0x06) {
                        [str appendFormat:@"%@=", sa];
                    } else {
                        [str appendFormat:@"%@ ", sa];
                    }
                }
                i += 1 + slength.len + slength.lenLen;
            }
            return str;
        }
        case 0x80:          // 直接输出
            return [self octetStringFromValue:data begin:begin length:length];
        case 0xa0:          //
        case 0xa1:          //
        case 0xa2:          //
        case 0xa3:          //
        case 0xa4:          //
            return [self value:data begin:begin + 1 + length.lenLen];
        default:
            break;
    }
    return  @"";
}

// 解析：Bool类型
+ (NSString *)boolFromValue:(char *)data begin:(int)begin length:(CertItemLength *)length {
    return (uint8_t)data[begin+1+length.lenLen] == 0xff ? @"true" : @"false";
}

// 解析：Int类型
+ (NSString *)intFromValue:(char *)data begin:(int)begin length:(CertItemLength *)length {
    NSString *str = [self octetStringFromValue:data begin:begin length:length];
    return [NSString stringWithFormat:@"%lu", strtoul(str.UTF8String, 0, 16)];
}

// 解析：Octet String 字节码串 类型
+ (NSString *)octetStringFromValue:(char *)data begin:(int)begin length:(CertItemLength *)length {
    NSMutableString *str = [NSMutableString string];
    for (int t = 0; t < length.len; t++) {
        [str appendFormat:@"%02x", (uint8_t)data[begin+1+length.lenLen+t]];
    }
    return str;
}

// 解析：UASCII字符串,IA5String类型
+ (NSString *)uasciiStringFromValue:(char *)data begin:(int)begin length:(CertItemLength *)length {
    NSMutableString *str = [NSMutableString string];
    for (int t = 0; t < length.len; t++) {
        [str appendFormat:@"%c", data[begin+1+length.lenLen+t]];
    }
    return str;
}

// 解析：oid 对象标识符
+ (NSString *)oidFromValue:(char *)data begin:(int)begin length:(CertItemLength *)length {
    int i = begin + 1 + length.lenLen;
    int oiFirst = data[i] & 0x7f;
    int oiIndex = MIN(oiFirst / 40, 2);
    NSMutableString *oid = [NSMutableString stringWithFormat:@"%d.%d", oiIndex, oiFirst - 40 * oiIndex];
    oiIndex = 2;
    oiFirst = 0;
    for (int t = 1; t < length.len; t++) {
        oiFirst <<= 7;
        oiFirst += data[i+t] & 0x7f;
        if (!(data[i + t] & 0x80)) {
            [oid appendFormat:@".%d", oiFirst];
            oiIndex += 1;
            oiFirst = 0;
        }
    }
    
    return oid;
}

// 解析：UTF8 String类型
+ (NSString *)utf8StringFromValue:(char *)data begin:(int)begin length:(CertItemLength *)length {
    int i = begin + 1 + length.lenLen;
    NSData *sData = [NSData dataWithBytes:data + i length:length.len];
    return [[NSString alloc] initWithData:sData encoding:NSUTF8StringEncoding];
}

// 解析：Unicode String类型
+ (NSString *)unicodeStringFromValue:(char *)data begin:(int)begin length:(CertItemLength *)length {
    int i = begin + 1 + length.lenLen;
    NSData *sData = [NSData dataWithBytes:data + i length:length.len];
    return [[NSString alloc] initWithData:sData encoding:NSUnicodeStringEncoding];
}

// 解析：Unicode String类型
+ (NSString *)utimeStringFromValue:(char *)data begin:(int)begin length:(CertItemLength *)length {
    NSString *str = [self uasciiStringFromValue:data begin:begin length:length];
    if (str.length > 0) {
        NSMutableString *time = [NSMutableString stringWithFormat:@"20%@", str];
        if (time.length > 4) {
            [time insertString:@"-" atIndex:4];     // 2021-0301133223Z
        }
        if (time.length > 7) {
            [time insertString:@"-" atIndex:7];     // 2021-03-01133223Z
        }
        if (time.length > 10) {
            [time insertString:@" " atIndex:10];     // 2021-03-01 133223Z
        }
        if (time.length > 13) {
            [time insertString:@":" atIndex:13];     // 2021-03-01 13:3223Z
        }
        if (time.length > 16) {
            [time insertString:@":" atIndex:16];     // 2021-03-01 13:32:23Z
        }
        if ([time hasSuffix:@"Z"]) {
            [time deleteCharactersInRange:NSMakeRange(time.length-1, 1)];
        }
    }
    return str;
}

@end
